/* SOLCM.C */

#include <solipeg.g>
#include <solipeg.rsg>
#include <hwim.h>

GLREF_D PR_SOLENG *             soleng ;
GLREF_D PR_APPMAN * const       w_am ;
GLREF_D PR_WSERV *              w_ws ;
GLREF_D PR_DLGBOX *             DatDialogPtr ;
GLREF_D TEXT *                  DatApp1 ;

// Launch a specific dialog
LOCAL_C INT LaunchDialog(INT class, INT resid, VOID *rbuf) {
    DL_DATA     dld ;

    dld.id = resid ;
    dld.rbuf = rbuf ;
    dld.pdlg = NULL ;
    return(hLaunchDial(CAT_SOLIPEG_SOLIPEG, class, &dld)) ;
}


#pragma METHOD_CALL


/************************************/
/* Dialog Subclass Methods          */
/************************************/

// Initialization for Open/Save dialogs
METHOD VOID soldlg_open_dl_dyn_init(PR_DLGBOX *self) {
    p_send4(    DatDialogPtr,
                O_WN_SET,
                1,
                ((SOLRBUF *) self->dlgbox.rbuf)->strFilename ) ;
    self->dlgbox.helprid = RH_LIBRARY ;
}

// Keypress handling for ENTER in Open/Save Dialog
METHOD INT soldlg_open_dl_key(  PR_DLGBOX *     self,
                                INT             index,
                                INT             keycode,
                                INT             actbut ) {
    p_send4(    DatDialogPtr,
                O_WN_SENSE,
                1,
                ((SOLRBUF *) self->dlgbox.rbuf)->strFilename ) ;
    return(WN_KEY_CHANGED) ;
}

// Initialization for Options dialog
METHOD VOID soldlg_options_dl_dyn_init(PR_DLGBOX *self) {
    INT     iLp ;

    for ( iLp = 0 ; iLp < 5 ; iLp++ ) {
        hDlgSetChlist(iLp + 1, *(&soleng->soleng.shape + iLp)) ;
    }
    self->dlgbox.helprid = RH_OPTIONS ;
}

// Keypress handling for ENTER in Options dialog
METHOD INT soldlg_options_dl_key(   PR_DLGBOX *     self,
                                    INT             index,
                                    INT             keycode,
                                    INT             actbut ) {
    INT     iLp ;

    for ( iLp = 0 ; iLp < 5 ; iLp++ ) {
        *(&soleng->soleng.shape + iLp) = hDlgSenseChlist(iLp + 1) ;
    }
    return(WN_KEY_CHANGED) ;
}

// Initialization for Library dialog
METHOD VOID soldlg_library_dl_dyn_init(PR_DLGBOX *self) {
    hDlgSetChlist(1, soleng->soleng.ridDefault) ;
    self->dlgbox.helprid = RH_LIBRARY ;
}

// Keypress handling for ENTER in Library dialog
METHOD INT soldlg_library_dl_key(   PR_DLGBOX *     self,
                                    INT             index,
                                    INT             keycode,
                                    INT             actbut ) {
    soleng->soleng.ridDefault = hDlgSenseChlist(1) ;
    return(WN_KEY_CHANGED) ;
}

// External library choice list dynamic initialization
METHOD VOID soldlg_ext_lib_dl_dyn_init(PR_DLGBOX * self) {
    TEXT            buffer[P_FNAMESIZE] ;
    SE_CHLIST       sc ;

    p_send4(    ((PR_SOLEL *) self->dlgbox.rbuf)->solel.pRsc,
                O_RS_READ_BUF,
                3,
                buffer ) ;
    if ( buffer[0] ) {
        hDlgSetText(0, buffer) ;
    }
    sc.set_flags = SE_CHLIST_DATA | SE_CHLIST_RETAIN ;
    sc.data = ((PR_SOLEL *) self->dlgbox.rbuf)->solel.pData ;
    hDlgSet(1, &sc) ;
    self->dlgbox.helprid = RH_LIBRARY ;
}

// External library choice list accept
METHOD INT soldlg_ext_lib_dl_key(   PR_DLGBOX *     self,
                                    INT             index,
                                    INT             keycode,
                                    INT             actbut ) {
    p_send4(    soleng,
                O_ENG_EXTERNAL_LIBRARY,
                self->dlgbox.rbuf,
                hDlgSenseChlist(1) ) ;
    return(WN_KEY_CHANGED) ;
}

// Statistics dialog dynamic initialization
METHOD VOID soldlg_stats_dl_dyn_init(PR_DLGBOX * self) {
    TEXT            buffer[32] ;
    INT             iLp ;
    INT             fFirst = TRUE ;
    TEXT *          p ;

    buffer[p_gltob(buffer, soleng->soleng.time, 10)] = '\x0' ;
    hDlgSetText(1, buffer) ;
    if ( soleng->soleng.time ) {
        buffer[p_gltob(buffer, soleng->soleng.total / soleng->soleng.time, 10)] = '\x0' ;
        hDlgSetText(2, buffer) ;
    }

    for ( buffer[0] = '\x0', p = &buffer[0], iLp = 0 ; iLp < 5 ; iLp++ ) {
        if ( soleng->soleng.results[iLp] ) {
            if ( !fFirst ) {
                *p++ = ',' ;
                *p++ = ' ' ;
            }
            fFirst = FALSE ;
            p += p_gtob(p, soleng->soleng.results[iLp], 10) ;
            *p = '\x0' ;
        }
    }
    hDlgSetText(3, buffer) ;

    self->dlgbox.helprid = RH_MAIN ;
}

/************************************/
/* Command Manager Subclass Methods */
/************************************/

// Handle the exit - saving the board position to env
METHOD VOID solcm_com_exit(PR_SOLCM *self) {
    p_setenviron(   DatApp1,
                    p_slen(DatApp1),
                    &soleng->soleng.show,
                    sizeof(soleng->soleng.show) +
                    sizeof(soleng->soleng.sound) +
                    sizeof(soleng->soleng.winpos) +
                    sizeof(soleng->soleng.results) +
                    sizeof(soleng->soleng.total) +
                    sizeof(soleng->soleng.time) ) ;
    p_exit(0) ;
}

// Handle the mode change due to diamond key
METHOD VOID solcm_com_mode_change(PR_SOLCM *self, INT back) {
    p_send3(soleng, O_ENG_MODE_CHANGE, back) ;
}

// New game command
METHOD VOID solcm_scm_new(PR_SOLCM *self) {
    if ( hConfirm(RS_NEW_GAME) ) {
        p_send2(soleng, O_ENG_NEW_GAME) ;
    }
}

// Open game command
METHOD VOID solcm_scm_open(PR_SOLCM *self, INT comid) {
    SOLRBUF     rb ;
    INT         iResID ;

    hLoadResBuf(    comid == O_SCM_EXTERNAL ? RS_DEF_EXTERNAL : RS_DEFNAME,
                    rb.strFilename ) ;

    switch ( comid ) {
        case O_SCM_OPEN :
            iResID = OPEN_DIALOG ;
            break ;

        case O_SCM_SAVE :
            iResID = SAVE_DIALOG ;
            break ;

        case O_SCM_EXTERNAL :
            iResID = OPEN_EXTERNAL_DIALOG ;
            break ;

        default :
            return ;
    }

    if ( !LaunchDialog(C_SOLDLG_OPEN, iResID, &rb) ) {
        return ;
    }

    if ( comid == O_SCM_EXTERNAL ) {
        PR_SOLEL *      pEL ;

        pEL = p_new(CAT_SOLIPEG_SOLIPEG, C_SOLEL) ;
        if ( p_send5(   pEL,
                        O_EL_INIT,
                        rb.strFilename,
                        self->solcm.strLibID,
                        self->solcm.wMinLibVer ) ) {
            p_send5(w_am, O_AM_NOTIFY, RS_BADFILE, NULL, NULL) ;
        }
        else {
            LaunchDialog(C_SOLDLG_EXT_LIB, EXTERNAL_LIBRARY_DIALOG, pEL) ;
        }

        hDestroy(pEL) ;
    }
    else {
        p_send3(    soleng,
                    comid == O_SCM_OPEN ? O_ENG_OPEN_GAME : O_ENG_SAVE_GAME,
                    rb.strFilename) ;
        p_send2(soleng, O_ENG_UPDATE_BOARD) ;
    }
}

// Use library command
METHOD VOID solcm_scm_library(PR_SOLCM *self) {
    LaunchDialog(C_SOLDLG_LIBRARY, LIBRARY_DIALOG, NULL) ;

    p_send2(soleng, O_ENG_NEW_GAME) ;
}

// Launch the Options dialog and reset board as necessary
METHOD VOID solcm_scm_options(PR_SOLCM *self) {
    UWORD   uwOldShape ;
    UWORD   uwOldRules ;
    UWORD   uwOldShow ;

    uwOldShape = soleng->soleng.shape ;
    uwOldRules = soleng->soleng.rules ;
    uwOldShow = soleng->soleng.show ;

    LaunchDialog(C_SOLDLG_OPTIONS, OPTIONS_DIALOG, NULL) ;

    if ( soleng->soleng.shape != uwOldShape ) {
        p_send2(soleng, O_ENG_SHAPE) ;
    }
    else if ( soleng->soleng.rules != uwOldRules ) {
        p_send2(soleng, O_ENG_UPDATE_BOARD) ;
    }
    else if ( soleng->soleng.show != uwOldShow ) {
        wInvalidateWin(w_ws->wserv.cli->win.id) ;
    }

    p_send3(w_ws->wserv.cli, O_WN_REPOS, soleng->soleng.winpos) ;
}

// Use statistics command
METHOD VOID solcm_scm_statistics(PR_SOLCM *self) {
    LaunchDialog(C_SOLDLG_STATS, STATS_DIALOG, NULL) ;
}

// Solipeg Command Manager Initialization
METHOD VOID solcm_com_init(PR_SOLCM *self) {
    hLoadResource(RS_LIBID, &self->solcm.strLibID) ;
    hLoadResBuf(RS_MINLIBVER, &self->solcm.wMinLibVer) ;
}

/************************************/
/* External Library Class Methods   */
/************************************/

// Initialize an external library for loading
METHOD INT solel_el_init(   PR_SOLEL *  self,
                            TEXT *      strFilename,
                            TEXT *      strReqID,
                            WORD        wMinLibVer ) {
    TEXT *      strLibID = NULL ;
    INT         iRet ;
    INT         iLp ;
    TEXT        buf[33] ;

    self->solel.pRsc = p_new(CAT_SOLIPEG_OLIB, C_RSCFILE) ;
    p_send3(self->solel.pRsc, O_RS_INIT, strFilename) ;

    p_send4(self->solel.pRsc, O_RS_READ, 1, &strLibID) ;
    iRet = p_scmp(strLibID, strReqID) ;
    p_free(strLibID) ;
    if (iRet)
        return(1) ;

    p_send4(self->solel.pRsc, O_RS_READ_BUF, 2, &self->solel.wLibVer) ;
    if ( self->solel.wLibVer > wMinLibVer )
        return(1) ;

    p_send4(self->solel.pRsc, O_RS_READ_BUF, 4, &self->solel.bLibSize) ;

    self->solel.pData = p_new(CAT_SOLIPEG_OLIB, C_VASTR) ;
    p_send3(self->solel.pData, O_VA_INIT, 32) ;
    for ( iLp = 5 ; iLp < 5 + self->solel.bLibSize ; iLp++ ) {
        p_send4(    self->solel.pRsc,
                    O_RS_READ_BUF,
                    iLp,
                    buf ) ;
        p_send5(    self->solel.pData,
                    O_VA_INSERTM,
                    self->solel.pData->varoot.nrec,
                    buf,
                    1 ) ;
    }

    return(0) ;
}

// Read a game by number
METHOD VOID solel_el_read(  PR_SOLEL *  self,
                            VOID **     ppBuf,
                            INT         iIndex ) {
    p_send4(    self->solel.pRsc,
                O_RS_READ,
                5 + self->solel.bLibSize + iIndex,
                ppBuf ) ;
}

